package baidu.com.matedemo.pair;

import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import com.baidu.duer.libcore.util.ConsoleLogger;
import com.baidu.duer.smartmate.duerlink.bean.DuerlinkError;
import com.baidu.duer.smartmate.out.DuerDevice;
import com.baidu.duer.smartmate.out.OauthParam;
import com.baidu.duer.smartmate.out.oauth.IOauthCallback;
import com.baidu.duer.smartmate.out.oauth.IResponseCallback;
import com.baidu.duer.smartmate.protocol.dlp.bean.autentication.DeviceCodePairReturnPayload;
import com.baidu.duer.smartmate.proxy.IConnectionListener;
import com.baidu.duer.smartmate.proxy.bean.AuthenticationMessage;
import com.baidu.duer.smartmate.proxy.controller.AuthenticationObserver;
import com.leon.parser.JsonHelper;

import java.net.URLDecoder;

/**
 * Created by sunjian11 on 18/3/1.
 * 合作方标准的授权方案，合作方需要:
 * 1) 在百度开放平台上追加如下redirect_url（与之前的回调地址逗号分隔）
 * https://xiaodu.baidu.com/saiya/device/oauthCallback?client_id=申请的clientId
 * 2) 让PM给度秘负责授权的研发发邮件备案
 */

public class OauthCodePairV2 implements IDevicePair, IConnectionListener, AuthenticationObserver {
    private static final int PASSPORT_PAIR_TIMEOUT = 30 * 1000;

    private Activity mActivity = null;
    private DuerDevice mDuerDevice = null;
    private IResponseCallback mCallback = null;
    private Handler mHandler = new Handler(Looper.getMainLooper());

    private Runnable mPassportPairTimeoutRunnable = new Runnable() {
        @Override
        public void run() {
            mCallback.onError(DuerlinkError.DLP_PASSPORT_PAIR_TIMEOUT.ordinal(),
                    DuerlinkError.DLP_PASSPORT_PAIR_TIMEOUT.toString());
            stopPair();
        }
    };

    @Override
    public void startPair(final Activity activity,
                          final DuerDevice duerDevice,
                          final IResponseCallback callback) {
        if (activity == null || duerDevice == null || callback == null) {
            return;
        }
        mActivity = activity;
        mDuerDevice = duerDevice;
        mCallback = callback;
        mDuerDevice.getControllerManager().registerAuthenticationObserver(this);
        mDuerDevice.connect(mActivity, this);
    }

    @Override
    public void stopPair() {
        mHandler.removeCallbacks(mPassportPairTimeoutRunnable);
        if (mDuerDevice != null) {
            mDuerDevice.getControllerManager().unregisterAuthenticationObserver(this);
            mDuerDevice.unregisterConnectionListener(this);
            mDuerDevice = null;
        }
    }

    @Override
    public void onConnected() {
        OauthParam param = getDeviceOauthParam(mDuerDevice);
        mDuerDevice.oauthDevice(mActivity, param, new IOauthCallback() {
            @Override
            public void onFinished(String message) {
                ConsoleLogger.printInfo(OauthCodePairV2.class, message);
                if (!TextUtils.isEmpty(message) && message.startsWith("dueros://close?result=")) {
                    message = message.substring("dueros://close?result=".length());
                    try {
                        message = URLDecoder.decode(message, "utf-8");
                        if (!TextUtils.isEmpty(message)) {
                            OauthResult oauthResult = new JsonHelper().fromJson(message, OauthResult.class);
                            if (oauthResult.getStatus() != 0) {
                                mCallback.onError(DuerlinkError.OAUTH_FAIL.ordinal(), message);
                                stopPair();
                                return;
                            }
                        }
                    } catch (Exception e) {
                        mCallback.onError(DuerlinkError.OAUTH_FAIL.ordinal(), message);
                        stopPair();
                        return;
                    }

                    mDuerDevice.getControllerManager().passportPair();
                    mHandler.postDelayed(mPassportPairTimeoutRunnable, PASSPORT_PAIR_TIMEOUT);
                }
            }

            @Override
            public void onError(int code, String message) {
                mCallback.onError(code, message);
                stopPair();
            }
        });
    }

    @Override
    public void onLocalConnected() {

    }

    @Override
    public void onConnectionFailed() {
        mCallback.onError(DuerlinkError.DLP_CONNECT_FAIL.ordinal(),
                DuerlinkError.DLP_CONNECT_FAIL.toString());
        stopPair();
    }

    @Override
    public void onDisconnected() {

    }

    @Override
    public void onDataChanaged(String event, AuthenticationMessage message) {
        if ("PassportPairReturn".equals(event)) {
            mHandler.removeCallbacks(mPassportPairTimeoutRunnable);
            if (message != null && message.getStatus() == 0) {
                mCallback.onSuccess();
            } else {
                mCallback.onError(DuerlinkError.DLP_PASSPORT_PAIR_FAIL.ordinal(),
                        DuerlinkError.DLP_PASSPORT_PAIR_FAIL.toString());
            }
            stopPair();
        }
    }

    @Override
    public void onDeviceCodePairReturn(DeviceCodePairReturnPayload payload) {

    }

    /****
     * 配网完成后需要对设备授权时，需要配置的Oauth信息，
     * 配网-->登录并授权-->配对；
     * 在百度开放平台上追加下redirect_url： https://xiaodu.baidu.com/saiya/device/oauthCallback?client_id=申请的clientId   （与之前的逗号分隔）
     * @param device
     * @return
     */
    private OauthParam getDeviceOauthParam(DuerDevice device) {
        OauthParam param = new OauthParam();
        param.setClientId(device.getClientId());
        param.setRedirectUri("https://xiaodu.baidu.com/saiya/device/oauthCallback?client_id=" + device.getClientId());
        param.setScope("");
        param.setState("{\"device_id\":\"" + device.getDeviceId() + "\"," + "\"redirect_to_dueros_close\":1" + "}");
        return param;
    }

    public class OauthResult {
        private int status;
        private String msg;
        private String logid;

        public int getStatus() {
            return status;
        }

        public void setStatus(int status) {
            this.status = status;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public String getLogid() {
            return logid;
        }

        public void setLogid(String logid) {
            this.logid = logid;
        }
    }
}
